$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + '/lib')

require 'uranium/constants'
require 'uranium/dbwrapper'
require 'uranium/testrunner'
require 'uranium/utils'
require 'socket'
require 'cgi'

at_exit{
  UraniumListener.close
}

class UraniumListener
  @@server = TCPServer.new('0.0.0.0', 3000)
  
  def self.close
    @@server.close if @@server
  end
  
  def self.run
    loop do
      begin
        self.accept(@@server.accept_nonblock)
      rescue Errno::EWOULDBLOCK
      end
      sleep 0.1
    end
  end

  def self.accept(session)
    Thread.new do
      begin
        request_parts  = session.gets.split(' ')
        path,query_str = CGI.unescape(request_parts[1]).split('?')
       
        if (path=='/do')
          params = Hash.new
          
          if query_str
            query_str.split('&').each do |p|
              k,v = p.split('=')
              params[k] = v
            end
          end
        
          params['sock'] = session
          result   = self.handle_request(params)
          response = "HTTP/1.1 200/OK\nContent-type: text/html\nContent-length: #{result.length}\n\n#{result}"
          session.print response
        else
          session.print "HTTP/1.1 403/OK\rContent-type: text/html\r\n\r\n403: Forbidden"
        end
      rescue Exception => e
        Log.debug e.inspect
        Log.debug e.backtrace.inspect
      ensure
        sleep 0.1
        session.close
      end
    end
  end

  def self.get_pids(params=nil)
    result = Hash.new
    
	if is_windows?
      lines = `tasklist /V`
    else
      lines = `ps|grep run.rb`
      lines = lines.split("\n")
    end
      
    lines.each do |line|
      if (line.match(/-r=/))
        run_id = line.match(/-r=(\d*)\b/).to_a[1]
        pid = line.match(/(\d+)\b/).to_a[1]
        
        result[run_id] = pid
      end
    end
        
    return result
  end

  def self.handle_request(params)
    case params['command']
      when 'bamboo'
        return self.bamboo(params)
      when 'runAll'
        return self.run_all(params)
      when 'retryFails'
        return self.retry_failed_cases(params)
      when 'runCases'
        return self.run_cases(params)
      when 'runSuite'
        return self.run_suite(params)
      when 'stop':
        self.stop(params['runId'])
        return self.stop(params['runId'])
      when 'listSuites'
        return `ruby "#{BASE_PATH}/run.rb" --list-suites`
      when 'getSource'
        return self.get_source(params['path'])
      when 'stop'
        return self.stop(params['runId'])
      when 'getActiveRuns'
        return toJSON({'runIds' => self.get_pids.keys})
      when 'retryFailedCases'
        return self.retry_failed_cases(params)
      when 'continue'
        return self.continue_run(params)
      when 'getPids':
        return toJSON(self.get_pids)
      when 'getBrowsers':
        return toJSON(get_browser_versions)
      else
		return {"state" => "P", "msg" => "Unknown command #{params['command']}"}.to_json
    end
  end
  
  def self.run_suite(params)
    spawn_process("ruby \"#{BASE_PATH}/run.rb\" -r=#{params['runId']} -s=#{params['suiteId']}", params['sock'])
    
	return {"state" => "P", "msg" => "Running #{params['runId']}"}.to_json
  end  
  
  def self.retry_failed_cases(params)    
    spawn_process("ruby \"#{BASE_PATH}/run.rb\" -r=#{params['runId']} --all-fails", params['sock'])
    
	return {"state" => "P", "msg" => "Running #{params['runId']}"}.to_json
  end
  
  def self.continue_run(params)
    spawn_process("ruby \"#{BASE_PATH}/run.rb\" -r=#{params['runId']} --continue", params['sock'])
    
	return {"state" => "P", "msg" => "Running #{params['runId']}"}.to_json
  end
  
  def self.stop(run_id)
    pids   = self.get_pids
    pid    = pids[run_id]
    
    Log.debug "trying to kill #{pid}"
    if (pid != nil)
      kill(pid)
      UraniumQuery.finalize_run(run_id)
	  return {"state" => "P", "msg" => "done"}.to_json
    else
	  return {"state" => "F", "msg" => "No processes for run #{run_id}"}.to_json
    end
  end
  
  def self.get_source(path)
    begin
      return File.read(File.dirname(__FILE__) + "/" + path)
    rescue
	  return {"state" => "P", "msg" => "Could not open file"}.to_json
    end
  end
  
  def self.run_all(params)
    spawn_process("ruby \"#{BASE_PATH}/run.rb\" -r=#{params['runId']}", params['sock'])
    
	return {"state" => "P", "msg" => "Running #{params['runId']}"}.to_json
  end
	
	def self.run_cases(params)
    spawn_process("ruby \"#{BASE_PATH}/run.rb\" -r=#{params['runId']} -c=#{params['name']}\\|#{params['suiteName']}" )

	return {"state" => "P", "msg" => "Running #{params['runId']}"}.to_json
	end
end

UraniumListener.run

